<?php

namespace lib\Server\Http;

class Response
{

	private $http_protocol = 'HTTP/1.1';
	private $status_code   = '200';

	private $head   = [];
	private $body   = null;
	private $cookie = null;

	private $request;
	private $response;

	private $HTTP_HEADERS
		= [
			100 => "100 Continue",
			101 => "101 Switching Protocols",
			200 => "200 OK",
			201 => "201 Created",
			204 => "204 No Content",
			206 => "206 Partial Content",
			300 => "300 Multiple Choices",
			301 => "301 Moved Permanently",
			302 => "302 Found",
			303 => "303 See Other",
			304 => "304 Not Modified",
			307 => "307 Temporary Redirect",
			400 => "400 Bad Request",
			401 => "401 Unauthorized",
			403 => "403 Forbidden",
			404 => "404 Not Found",
			405 => "405 Method Not Allowed",
			406 => "406 Not Acceptable",
			408 => "408 Request Timeout",
			410 => "410 Gone",
			413 => "413 Request Entity Too Large",
			414 => "414 Request URI Too Long",
			415 => "415 Unsupported Media Type",
			416 => "416 Requested Range Not Satisfiable",
			417 => "417 Expectation Failed",
			500 => "500 Internal Server Error",
			501 => "501 Method Not Implemented",
			503 => "503 Service Unavailable",
			506 => "506 Variant Also Negotiates"
		];

	/**
	 * 静态文件类型
	 *
	 * @var array
	 */
	static public $assetTypes
		= [
			'js' => 'application/x-javascript',
			'css' => 'text/css',
			'png' => 'image/png',
			'jpg' => 'image/jpeg',
			'jpeg' => 'image/jpeg',
			'gif' => 'image/gif',
			'json' => 'application/json',
			'xml' => 'application/xml',
			'svg' => 'image/svg+xml',
			'woff' => 'application/font-woff',
			'woff2' => 'application/font-woff2',
			'ttf' => 'application/x-font-ttf',
			'eot' => 'application/vnd.ms-fontobject',
			'html' => 'text/html',
		];

	function __construct($request, $response = null)
	{
		$this->request  = $request;
		$this->response = $response;
	}

	public function bodyIsNull()
	{
		return $this->body === null;
	}

	/**
	 * 自定义tcp_http 使用
	 * @return string
	 */
	public function __toString()
	{
		if (!isset($this->head['Cache-Control'])) $this->setHeader('Cache-Control', 'no-cache');
		if (!isset($this->head['Connection'])) $this->setHeader('Connection', 'Keep-Alive');
		$this->setHeader('Server', 'C-sh/0.0.1');


		if (!$this->body && in_array($this->status_code, $this->HTTP_HEADERS)) {
			$this->withJson([
				'code' => $this->status_code,
				'message' => $this->HTTP_HEADERS[$this->status_code]
			]);
		}

		if (!isset($this->head['Content-Length'])) {
			$this->setHeader('Content-Length', strlen($this->body));
		}


		$head = [];
		foreach ($this->head as $key => $val) {
			$head [] = "{$key}: {$val}";
		}

		$cookie = '';
		if (!empty($this->cookie) and is_array($this->cookie)) {
			foreach ($this->cookie as $v) {
				$cookie .= "Set-Cookie: $v\r\n";
			}
		}


		$head = join("\r\n", $head) . $cookie;

		$responseBody
			= <<<RESPONSE
$this->http_protocol {$this->HTTP_HEADERS[$this->status_code]}\r\n$head\r\n\r\n$this->body
RESPONSE;

//		echo $responseBody;
		return $responseBody;

	}

	/**
	 * swoole http_server 使用
	 * @return mixed
	 */
	public function httpResponseEnd()
	{
		if ($this->response) {

			echo 'http_server close tcp connent.';
			$this->setHeader('Server', 'C-sh/0.0.1');
			if (is_array($this->head)) {
				foreach ($this->head as $key => $val) {
					$this->response->header($key, $val);
				}
			}

			if (is_array($this->cookie)) {
				foreach ($this->cookie as $v) {
					$this->response->header('Set-Cookie', $v);
				}
			}


			return $this->response->end($this->body);
		}
	}

	public function setHeader($name, $value)
	{
		$this->head[$name] = $value;
		return $this;
	}

	public function setBody($raw_body)
	{
		$this->body = $raw_body;
		return $this;
	}

	public function setStatusCode($code)
	{
		$this->status_code = $code;
		return $this;
	}

	public function setContentType($content_type)
	{

		$this->setHeader('Content-Type', isset(self::$assetTypes[$content_type]) ? self::$assetTypes[$content_type] : $content_type);
		return $this;
	}

	public function with($string)
	{
		$this->withHtml($string);
	}

	public function withHtml($html)
	{
		$this->setHeader('Content-Type', self::$assetTypes['html']);
		$this->body = $html;

		$this->httpResponseEnd();
	}

	public function withJson($data)
	{
		if (isset($data['error_code'])) {
			$data['error_code'] = (int)$data['error_code'];
		}
		else {
			$data['error_code'] = 0;
		}

		$this->body = json_encode($data);
		$this->setHeader('Content-Type', 'application/json;charset=utf-8');
		$this->httpResponseEnd();
	}

	function noCache()
	{
		$this->head['Cache-Control'] = 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0';
		$this->head['Pragma']        = 'no-cache';
	}


	/**
	 * cookie
	 * @param $name
	 * @param null $value
	 * @param null $expire
	 * @param string $path
	 * @param null $domain
	 * @param null $secure
	 * @param null $http_only
	 * @return object
	 */
	function setCookie($name, $value = null, $expire = null, $path = '/', $domain = null, $secure = null, $http_only = null)
	{
		if ($this->response) {
			$this->response->cookie($name, $value, $expire, $path, $domain, $secure, $http_only);
		}
		else {
			if ($value == null) $value = 'deleted';
			$cookie = "$name=$value; expires=Tue, " . date("D, d-M-Y H:i:s T", $expire) . "; path=$path";
			if ($domain) $cookie .= "; domain=$domain";
			if ($http_only) $cookie .= '; httponly';
			$this->cookie[] = $cookie;
		}

		return $this;
	}
}

